package com.zbkj.admin.config;

import cn.hutool.extra.emoji.EmojiUtil;
import com.alibaba.fastjson.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.WebUtil;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
public class WechatOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User>, AuthenticationSuccessHandler {
    private final RestTemplate restTemplate = createRestTemplate();

    @Override
    public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2AuthenticationException {
        // 1. 获取必要参数
        String accessToken = request.getAccessToken().getTokenValue();
        String openid = request.getAdditionalParameters().get("openid").toString();
        String unionid = (String) request.getAdditionalParameters().get("unionid");
//        String identifier = unionid != null ? unionid : openid;

        // 2. 调用微信用户信息接口
        String userInfoUrl = String.format(
                "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s",
                accessToken, openid
        );

        ResponseEntity<String> response = restTemplate.getForEntity(userInfoUrl, String.class);

        // 3. 处理响应
        validateResponse(response);
        Map<String, Object> userAttributes = parseWechatResponse(JSON.parseObject(response.getBody(), Map.class));
        log.debug("开始获取微信用户信息，openid: {}", openid);
//        log.info("微信用户信息获取成功，昵称: {}", EmojiUtil.toAlias((String) userAttributes.get("nickname")));
        // 4. 构建用户对象
        return new WechatOAuth2User(
                unionid != null ? unionid : openid,
                userAttributes,
                "openid" // 使用微信的openid作为唯一标识字段名
        );
    }

    private RestTemplate createRestTemplate() {
        RestTemplate template = new RestTemplate();
        template.setErrorHandler(new WechatErrorHandler());
        return template;
    }

    private void validateResponse(ResponseEntity<String> response) {
        if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
            throw new OAuth2AuthenticationException("微信用户信息接口调用失败");
        }

        Map<String, Object> body = response.getBody().startsWith("{") ? JSON.parseObject(response.getBody(), Map.class) : null;
        if (body.containsKey("errcode")) {
            int errcode = (Integer) body.get("errcode");
            if (errcode != 0) {
                throw new OAuth2AuthenticationException(
                        "微信用户信息错误: " + body.get("errmsg")
                );
            }
        }
    }

    private Map<String, Object> parseWechatResponse(Map<String, Object> wechatResponse) {
        Map<String, Object> attributes = new LinkedHashMap<>();

        // 基础字段
        attributes.put("openid", wechatResponse.get("openid"));
        attributes.put("unionid", wechatResponse.get("unionid"));
        attributes.put("nickname", wechatResponse.get("nickname"));
        attributes.put("headimgurl", convertHttpsUrl(wechatResponse.get("headimgurl")));

        // 性别转换（微信：0-未知 1-男 2-女）
        Object sex = wechatResponse.get("sex");
        attributes.put("gender", sex != null ?
                switch ((Integer) sex) {
                    case 1 -> "male";
                    case 2 -> "female";
                    default -> "unknown";
                } : "unknown");

        // 地区信息
        attributes.put("country", wechatResponse.get("country"));
        attributes.put("province", wechatResponse.get("province"));
        attributes.put("city", wechatResponse.get("city"));

        return attributes;
    }

    private String convertHttpsUrl(Object url) {
        if (url == null) return null;
        String urlStr = url.toString();
        return urlStr.replace("http://", "https://");
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        WebUtil.renderJson(response, authentication.getPrincipal());
    }

    // 自定义用户实体类
    public static class WechatOAuth2User extends DefaultOAuth2User {
        private final String unionid;
        private final String openid;

        public WechatOAuth2User(String name, Map<String, Object> attributes, String userNameAttributeName) {
            super(Collections.emptyList(), attributes, userNameAttributeName);
            this.unionid = (String) attributes.get("unionid");
            this.openid = (String) attributes.get("openid");
        }

        // 添加微信特有属性访问方法
        public String getUnionid() {
            return unionid;
        }

        public String getOpenid() {
            return openid;
        }

        public String getNickname() {
            return (String) getAttributes().get("nickname");
        }

        public String getAvatarUrl() {
            return (String) getAttributes().get("headimgurl");
        }
    }

    // 错误处理器（复用之前的实现）
    private static class WechatErrorHandler extends DefaultResponseErrorHandler {
        @Override
        public void handleError(ClientHttpResponse response) throws IOException {
            String body = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
            throw new OAuth2AuthenticationException("微信接口异常: " + body);
        }
    }
}
